package cn.iocoder.yudao.module.trade.order.controller.admin;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.business.basic.pojo.vo.UserSimpleVO;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.api.member.user.MemberUserApi;
import cn.iocoder.yudao.module.api.promotion.combination.CombinationRecordApi;
import cn.iocoder.yudao.module.api.promotion.combination.dto.CombinationRecordRespDTO;
import cn.iocoder.yudao.module.api.promotion.groupon.GrouponPackageApi;
import cn.iocoder.yudao.module.api.promotion.groupon.dto.GrouponPackageRespDTO;
import cn.iocoder.yudao.module.api.shop.info.ShopInfoApi;
import cn.iocoder.yudao.module.api.shop.info.dto.ShopInfoDTO;
import cn.iocoder.yudao.module.api.shop.staff.ShopStaffApi;
import cn.iocoder.yudao.module.api.trade.order.dto.TradeOrderDeliveryDTO;
import cn.iocoder.yudao.module.trade.delivery.service.DeliveryPickUpStoreService;
import cn.iocoder.yudao.module.trade.delivery.vo.DeliveryPickUpStoreRespVO;
import cn.iocoder.yudao.module.trade.order.convert.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.order.dal.dataobject.TradeOrderDO;
import cn.iocoder.yudao.module.trade.order.dal.dataobject.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.order.dal.dataobject.TradeOrderLogDO;
import cn.iocoder.yudao.module.trade.order.service.TradeOrderLogService;
import cn.iocoder.yudao.module.trade.order.service.TradeOrderQueryService;
import cn.iocoder.yudao.module.trade.order.service.TradeOrderUpdateService;
import cn.iocoder.yudao.module.trade.order.service.ZXHXOrderSyncService;
import cn.iocoder.yudao.module.trade.order.vo.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.*;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

@Tag(name = "管理后台 - 交易订单")
@RestController
@RequestMapping("/trade/order")
@Validated
@Slf4j
public class TradeOrderController implements TradeOrderStatusNameGetter {

    @Resource
    private TradeOrderUpdateService tradeOrderUpdateService;
    @Resource
    private TradeOrderQueryService tradeOrderQueryService;
    @Resource
    private TradeOrderLogService tradeOrderLogService;
    @Resource
    private DeliveryPickUpStoreService deliveryPickUpStoreService;
    @Resource
    private ZXHXOrderSyncService zxhxOrderSyncService;

    @Resource
    private ShopInfoApi shopInfoApi;
    @Resource
    private ShopStaffApi shopStaffApi;
    @Resource
    private CombinationRecordApi combinationRecordApi;
    @Resource
    private GrouponPackageApi grouponPackageApi;
    @Resource
    private MemberUserApi memberUserApi;

    @GetMapping("/page")
    @Operation(summary = "获得交易订单分页")
    @PreAuthorize("@ss.hasPermission('trade:order:query')")
    public CommonResult<PageResult<TradeOrderPageItemRespVO>> getOrderPage(TradeOrderPageReqVO reqVO) {
        // 查询订单
        PageResult<TradeOrderDO> pageResult = tradeOrderQueryService.getOrderPage(reqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(PageResult.empty());
        }
        return toCommonResult(pageResult);
    }

    @GetMapping("/page-verify")
    @Operation(summary = "获得核销订单分页")
    @PreAuthorize("@ss.hasPermission('trade:order:query')")
    public CommonResult<PageResult<TradeOrderPageItemRespVO>> getVerifyOrderPage(TradeOrderPageForVerifyReqVO reqVO) {
        // 查询订单
        PageResult<TradeOrderDO> pageResult = tradeOrderQueryService.getOrderPageForVerify(reqVO);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return success(PageResult.empty());
        }
        return toCommonResult(pageResult);
    }

    private CommonResult<PageResult<TradeOrderPageItemRespVO>> toCommonResult(PageResult<TradeOrderDO> pageResult) {
        // 查询店铺信息
        Set<Long> shopIds = new HashSet<>(convertList(pageResult.getList(), TradeOrderDO::getShopId));
        Map<Long, ShopInfoDTO> shopMap = shopInfoApi.getShopInfoMap(shopIds);
        // 查询自提门店信息
        Set<Long> pickUpStoreIds = new HashSet<>(convertList(pageResult.getList(), TradeOrderDO::getPickUpStoreId));
        Map<Long, DeliveryPickUpStoreRespVO> pickUpStoreMap = deliveryPickUpStoreService.getDeliveryPickUpStoreMap(pickUpStoreIds);
        // 查询用户信息
        Set<Long> userIds = CollUtil.unionDistinct(convertList(pageResult.getList(), TradeOrderDO::getUserId),
                convertList(pageResult.getList(), TradeOrderDO::getBrokerageUserId, Objects::nonNull));
        Map<Long, UserSimpleVO> userMap = memberUserApi.getUserSimpleMap(userIds);
        // 查询订单项
        List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderIds(
                convertSet(pageResult.getList(), TradeOrderDO::getId));
        Set<Long> combinationRecordIds = convertSet(pageResult.getList(), TradeOrderDO::getCombinationRecordId);
        Map<Long, CombinationRecordRespDTO> combinationRecords = combinationRecordApi.getCombinationRecordsByIds(combinationRecordIds);
        Set<Long> grouponPackageIds = convertSet(pageResult.getList(), TradeOrderDO::getGrouponPackageId);
        Map<Long, GrouponPackageRespDTO> grouponPackageMap = grouponPackageApi.getMap(grouponPackageIds);
        // 最终组合
        PageResult<TradeOrderPageItemRespVO> data = TradeOrderConvert.INSTANCE.convertPage(pageResult, orderItems, userMap);
        data.getList().forEach(item -> {
            item.setShop(shopMap.get(item.getShopId()));
            item.setStatusName(assignStatusName(item.getDeliveryType(), item.getStatus(), item.getCommentStatus(), item.getRefundStatus(), item.getDineStatus()));
            if (CollUtil.isNotEmpty(item.getItems())) {
                item.setAfterSaleStatus(item.getItems().get(0).getAfterSaleStatus());
            }
            item.setPickUpStore(pickUpStoreMap.get(item.getPickUpStoreId()));
            CombinationRecordRespDTO combinationRecordRespDTO = combinationRecords.getOrDefault(item.getCombinationRecordId(), null);
            item.setCombinationStatus(combinationRecordRespDTO == null ? null : combinationRecordRespDTO.getStatus());
            if (item.getGrouponPackageId() != null && item.getGrouponPackageId() > 0) {
                item.setGrouponPackage(grouponPackageMap.getOrDefault(item.getGrouponPackageId(), null));
            }
        });
        return success(data);
    }

    @GetMapping("/summary")
    @Operation(summary = "获得交易订单统计")
    @PreAuthorize("@ss.hasPermission('trade:order:query')")
    public CommonResult<TradeOrderSummaryRespVO> getOrderSummary(TradeOrderPageReqVO reqVO) {
        return success(tradeOrderQueryService.getOrderSummary(reqVO));
    }

    @GetMapping("/get-detail")
    @Operation(summary = "获得交易订单详情")
    @Parameter(name = "id", description = "订单编号", required = true, example = "1")
    @PreAuthorize("@ss.hasPermission('trade:order:query')")
    public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
        // 查询订单
        TradeOrderDO order = tradeOrderQueryService.getOrder(id);
        return toCommonResult(order);
    }

    @GetMapping("/get-detail-by-no")
    @Operation(summary = "获得交易订单详情")
    @Parameter(name = "no", description = "订单编号", required = true, example = "TRD202504180909241")
    @PreAuthorize("@ss.hasPermission('trade:order:query')")
    public CommonResult<TradeOrderDetailRespVO> getOrderDetailByNo(@RequestParam("no") String no) {
        // 查询订单
        TradeOrderDO order = tradeOrderQueryService.getOrderByNo(no);
        return toCommonResult(order);
    }

    private CommonResult<TradeOrderDetailRespVO> toCommonResult(TradeOrderDO order) {
        if (order == null) {
            return success(null);
        }
        if (CollUtil.isNotEmpty(order.getSupplyRelatedNos())) {
            for (String supplyRelatedNo : order.getSupplyRelatedNos()) {
                zxhxOrderSyncService.syncOrderInfoAsync(supplyRelatedNo, order);
            }
        }

        // 查询订单项
        List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());

        // 拼接数据
        UserSimpleVO user = memberUserApi.getUser(order.getUserId());
        UserSimpleVO brokerageUser = order.getBrokerageUserId() != null ?
                memberUserApi.getUser(order.getBrokerageUserId()) : null;
        List<TradeOrderLogDO> orderLogs = tradeOrderLogService.getOrderLogListByOrderId(order.getId());
        TradeOrderDetailRespVO data = TradeOrderConvert.INSTANCE.convert(order, orderItems, orderLogs, user, brokerageUser);
        data.setShop(shopInfoApi.getShopInfo(order.getShopId()));
        data.setStatusName(assignStatusName(data.getDeliveryType(), data.getStatus(), data.getCommentStatus(), data.getRefundStatus(), data.getDineStatus()));
        data.setRiderStaff(shopStaffApi.getById(order.getRiderStaffId()));
        if (order.getCombinationRecordId() != null && order.getCombinationRecordId() > 0) {
            data.setCombinationRecord(combinationRecordApi.getCombinationRecordById(order.getCombinationRecordId()));
        }
        if (data.getGrouponPackageId() != null && data.getGrouponPackageId() > 0) {
            data.setGrouponPackage(grouponPackageApi.getDetail(data.getGrouponPackageId()));
        }
        return success(data);
    }

    @GetMapping("/get-express-track-list")
    @Operation(summary = "获得交易订单的物流轨迹")
    @Parameter(name = "id", description = "交易订单编号")
    @PreAuthorize("@ss.hasPermission('trade:order:query')")
    public CommonResult<List<?>> getOrderExpressTrackList(@RequestParam("id") Long id) {
        return success(TradeOrderConvert.INSTANCE.convertList02(
                tradeOrderQueryService.getExpressTrackList(id)));
    }

    @PutMapping("/delivery")
    @Operation(summary = "订单发货")
    @PreAuthorize("@ss.hasRole('shop_admin')")
    public CommonResult<Boolean> deliveryOrder(@Valid @RequestBody TradeOrderDeliveryDTO dto) {
        tradeOrderUpdateService.deliveryOrder(dto);
        return success(true);
    }

    @PutMapping("/update-remark")
    @Operation(summary = "订单备注")
    @PreAuthorize("@ss.hasRole('shop_admin')")
    public CommonResult<Boolean> updateOrderRemark(@Valid @RequestBody TradeOrderRemarkReqVO reqVO) {
        tradeOrderUpdateService.updateOrderRemark(reqVO);
        return success(true);
    }

    @PutMapping("/update-price")
    @Operation(summary = "订单调价")
    @PreAuthorize("@ss.hasRole('shop_admin')")
    public CommonResult<Boolean> updateOrderPrice(@Valid @RequestBody TradeOrderUpdatePriceReqVO reqVO) {
        tradeOrderUpdateService.updateOrderPrice(reqVO);
        return success(true);
    }

    @PutMapping("/update-address")
    @Operation(summary = "修改订单收货地址")
    @PreAuthorize("@ss.hasRole('shop_admin')")
    public CommonResult<Boolean> updateOrderAddress(@Valid @RequestBody TradeOrderUpdateAddressReqVO reqVO) {
        tradeOrderUpdateService.updateOrderAddress(reqVO);
        return success(true);
    }

    @PutMapping("/verify-by-id")
    @Operation(summary = "订单核销")
    @Parameter(name = "id", description = "交易订单编号")
    @PreAuthorize("@ss.hasAnyRoles('shop_admin', 'shop_staff')")
    public CommonResult<Boolean> verifyOrderById(@RequestParam("id") Long id) {
        tradeOrderUpdateService.verifyOrderByAdmin(getLoginUserId(), id);
        return success(true);
    }

    @PutMapping("/verify-by-verify-code")
    @Operation(summary = "订单核销")
    @Parameter(name = "verifyCode", description = "核销码")
    @PreAuthorize("@ss.hasAnyRoles('shop_admin', 'shop_staff')")
    public CommonResult<Boolean> verifyOrderByVerifyCode(@RequestParam("verifyCode") String verifyCode) {
        tradeOrderUpdateService.verifyOrderByAdmin(getLoginUserId(), verifyCode);
        return success(true);
    }

    @GetMapping("/get-by-verify-code")
    @Operation(summary = "查询核销码对应的订单")
    @Parameter(name = "verifyCode", description = "核销码")
    @PreAuthorize("@ss.hasAnyRoles('shop_admin', 'shop_staff')")
    public CommonResult<TradeOrderDetailRespVO> getByVerifyCode(@RequestParam("verifyCode") String verifyCode) {
        TradeOrderDO tradeOrder = tradeOrderUpdateService.getByVerifyCode(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), verifyCode);
        return success(TradeOrderConvert.INSTANCE.convert2(tradeOrder, null));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出订单 Excel")
    @PreAuthorize("@ss.hasPermission('trade:order:query')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportOrderExcel(@Valid TradeOrderPageReqVO pageReqVO,
                                 HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        // 查询订单
        List<TradeOrderPageItemRespVO> list = getOrderPage(pageReqVO).getData().getList();
        // 导出 Excel
        ExcelUtils.write(response, "交易订单.xls", "数据", TradeOrderBaseVO.class,
                BeanUtils.toBean(list, TradeOrderBaseVO.class));
    }

}
